package thread.sysChronize;

import java.util.Arrays;

/**
 * 银行账户转账案例，学习 线程不安全情况下， 加锁解决线程不安全问题
 * @Author Janson
 * @Date 2022/2/28 18:54
 * @Version 1.0
 */
public class TestSyncBank{
    private static final int ACCOUNTS = 100;
    private static final int INITIALBALANCE = 1000;
    private static final int MAXAMMOUNT = 1000;

    public static void main(String[] args) {
        Bank bank = new Bank(ACCOUNTS,INITIALBALANCE);
        //可重入锁，在run方法中加，或者 在 lambda 表达式中加上，
        //ReentrantLock reentrantLock = new ReentrantLock();
        for (int i = 0; i < ACCOUNTS; i++) {
                int fromaccount = i;
                //调用线程接口，采用lambda 表达式进行，也可以实现通过该接口，重写run方法
                Runnable runnable = ()->{
                    //reentrantLock.lock();
                        int  toaccount = (int) (ACCOUNTS * Math.random());
                        int amount = (int) (MAXAMMOUNT * Math.random());
                        //调用转账方法
                        bank.transfer(amount,fromaccount,toaccount);
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();

                    }finally {
                            //reentrantLock.unlock();
                        }
                };
                new Thread(runnable).start();
            }
    }
}

class Bank{
    private int[] account;
    private int initBalance;

    public Bank(int account,int initBalance) {
        this.account = new int[account];
        this.initBalance = initBalance;
        Arrays.fill(this.account,this.initBalance);
    }
    //转账方法
    //给 transfer 加锁synchronized，不然会出现线程不安全 ，加锁在方法上
    public synchronized void transfer(int amount,int fromaccount,int toaccount){
        System.out.println(Thread.currentThread());
        if (account[fromaccount] >= amount){
            account[fromaccount] -= amount;
        }else
            return;
        System.out.printf("%d from %d to %d\n",amount,fromaccount,toaccount);
        account[toaccount] += amount;
        System.out.println("各个账户的总余额:" + getTotalBalance());
    }
    //获取所有账户的余额，正常来说 是 100000
    private int getTotalBalance() {
        int sum = 0;
        for (int i = 0; i < account.length; i++) {
            sum += account[i];
        }
        return sum;
    }
}
